package cn.ocars.playgame.pencilstudy.ui.components

import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Path
import android.opengl.GLES20
import android.opengl.GLSurfaceView
import android.opengl.Matrix
import android.view.MotionEvent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.input.motionprediction.MotionEventPredictor
import cn.ocars.playgame.pencilstudy.model.Stroke
import cn.ocars.playgame.pencilstudy.model.StrokePoint
import cn.ocars.playgame.pencilstudy.services.MiniCPMVRecognitionService
import cn.ocars.playgame.pencilstudy.ui.theme.PrimaryBlue
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.FloatBuffer
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10
import kotlin.math.abs
import kotlin.math.sqrt

/**
 * MiniCPM书写卡片组件
 * 使用OpenGL ES和MotionEventPredictor实现低延迟的书写体验
 * 当用户完成对应笔画数书写后，调用MiniCPM进行评分
 */
@Composable
fun MiniCPMWritingCard(
    character: String,
    strokeCount: Int,
    onWritingComplete: (MiniCPMVRecognitionService.RecognitionResult) -> Unit,
    modifier: Modifier = Modifier,
    onClearClick: (() -> Unit)? = null
) {
    val context = LocalContext.current
    val coroutineScope = remember { CoroutineScope(Dispatchers.Main) }
    
    // 创建MiniCPM识别服务
    val recognitionService = remember { MiniCPMVRecognitionService(context) }
    
    // 初始化识别服务
    LaunchedEffect(recognitionService) {
        recognitionService.initialize()
    }
    
    // 释放识别服务资源
    DisposableEffect(recognitionService) {
        onDispose {
            recognitionService.release()
        }
    }
    
    val renderer = remember { 
        val glView = MiniCPMGLSurfaceView(context)
        MiniCPMWritingRenderer(glView, context, character, strokeCount, recognitionService, onWritingComplete, coroutineScope)
    }
    
    Box(
        modifier = modifier.size(150.dp),
        contentAlignment = Alignment.Center
    ) {
        AndroidView(
            modifier = Modifier.fillMaxSize(),
            factory = {
                val glView = MiniCPMGLSurfaceView(context)
                glView.setRenderer(renderer)
                renderer.setGLView(glView)
                
                // 设置渲染模式为RENDERMODE_WHEN_DIRTY，只在需要时渲染
                glView.renderMode = GLSurfaceView.RENDERMODE_WHEN_DIRTY
                
                // 设置触摸事件监听器
                glView.setOnTouchListener { view, event ->
                    renderer.handleTouchEvent(event, view.width, view.height)
                    true
                }
                
                glView
            }
        )
        
        // 橡皮图标
        androidx.compose.material3.IconButton(
            onClick = { 
                renderer.clear()
                onClearClick?.invoke()
            },
            modifier = Modifier
                .align(Alignment.TopEnd)
                .size(24.dp)
        ) {
            androidx.compose.material3.Icon(
                painter = androidx.compose.ui.res.painterResource(android.R.drawable.ic_menu_delete),
                contentDescription = "清除",
                tint = PrimaryBlue.copy(alpha = 0.7f),
                modifier = Modifier.size(16.dp)
            )
        }
        
        // 显示淡色字符提示
        androidx.compose.material3.Text(
            text = character,
            fontSize = 80.sp,
            fontWeight = androidx.compose.ui.text.font.FontWeight.Bold,
            color = PrimaryBlue.copy(alpha = 0.15f),
            textAlign = androidx.compose.ui.text.style.TextAlign.Center,
            modifier = Modifier.align(Alignment.Center)
        )
    }
}

/**
 * MiniCPM GLSurfaceView
 */
class MiniCPMGLSurfaceView(
    context: Context
) : GLSurfaceView(context) {

    init {
        // 设置OpenGL ES版本
        setEGLContextClientVersion(2)
        
        // 保留EGL上下文以避免重新创建
        preserveEGLContextOnPause = true
    }
}

/**
 * MiniCPM书写渲染器
 */
class MiniCPMWritingRenderer(
    private var glView: GLSurfaceView,
    private val context: Context,
    private val character: String,
    private val requiredStrokeCount: Int,
    private val recognitionService: MiniCPMVRecognitionService,
    private val onWritingComplete: (MiniCPMVRecognitionService.RecognitionResult) -> Unit,
    private val coroutineScope: CoroutineScope
) : GLSurfaceView.Renderer {
    
    // OpenGL相关变量
    private var shaderProgram: Int = 0
    private var positionHandle: Int = 0
    private var colorHandle: Int = 0
    private var mvpMatrixHandle: Int = 0
    
    // 视图尺寸
    private var viewWidth = 0
    private var viewHeight = 0
    
    // 矩阵
    private val mvpMatrix = FloatArray(16)
    private val projectionMatrix = FloatArray(16)
    private val viewMatrix = FloatArray(16)
    
    // 书写状态
    private var isWriting = false
    private var currentPath = Path()
    private var allPaths = mutableListOf<Path>()
    private var strokeCount = 0
    private var hasCompletedStrokes = false
    
    // 动作预测器
    private var motionEventPredictor: MotionEventPredictor? = null
    
    // 顶点缓冲区
    private var vertexBuffer: FloatBuffer? = null
    private var lineVertices = mutableListOf<Float>()
    private var lineWidths = mutableListOf<Float>() // 存储线宽
    private var currentLineWidth = 4.0f // 当前线宽
    
    // 分离的绘制数据
    private var currentStrokeVertices = mutableListOf<Float>()
    private var currentStrokeWidths = mutableListOf<Float>()
    private var completedStrokes = mutableListOf<StrokeData>()
    
    // 笔画数据（用于MiniCPM识别）
    private var currentStrokePoints = mutableListOf<StrokePoint>()
    private var allStrokePoints = mutableListOf<StrokePoint>()
    
    init {
        // 初始化矩阵
        Matrix.setIdentityM(mvpMatrix, 0)
        Matrix.setIdentityM(projectionMatrix, 0)
        Matrix.setIdentityM(viewMatrix, 0)
    }
    
    /**
     * 设置GLView引用
     */
    fun setGLView(view: GLSurfaceView) {
        glView = view
    }
    
    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
        // 设置清屏颜色
        GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f)
        
        // 启用抗锯齿
        GLES20.glEnable(GLES20.GL_BLEND)
        GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA)
        
        // 初始化着色器
        initShaders()
        
        // 初始化动作预测器
        motionEventPredictor = MotionEventPredictor.newInstance(glView)
    }
    
    override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
        // 设置视口尺寸
        GLES20.glViewport(0, 0, width, height)
        
        // 更新视图尺寸
        viewWidth = width
        viewHeight = height
    }
    
    override fun onDrawFrame(gl: GL10?) {
        // 清除屏幕
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
        
        // 绘制田字格
        drawGrid()
        
        // 绘制所有已完成的笔画
        synchronized(this) {
            completedStrokes.forEach { strokeData ->
                drawStrokeWithVariableWidth(strokeData.vertices, strokeData.widths, false)
            }
        }
        
        // 绘制当前正在书写的笔画
        synchronized(this) {
            if (isWriting && currentStrokeVertices.isNotEmpty()) {
                drawStrokeWithVariableWidth(currentStrokeVertices, currentStrokeWidths, true)
            }
        }
    }
    
    /**
     * 初始化着色器
     */
    private fun initShaders() {
        // 顶点着色器代码
        val vertexShaderCode =
            "uniform mat4 uMVPMatrix;" +
            "attribute vec4 vPosition;" +
            "void main() {" +
            "  gl_Position = uMVPMatrix * vPosition;" +
            "}"
        
        // 片段着色器代码
        val fragmentShaderCode =
            "precision mediump float;" +
            "uniform vec4 vColor;" +
            "void main() {" +
            "  gl_FragColor = vColor;" +
            "}"
        
        // 编译顶点着色器
        val vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode)
        
        // 编译片段着色器
        val fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode)
        
        // 创建着色器程序
        shaderProgram = GLES20.glCreateProgram()
        GLES20.glAttachShader(shaderProgram, vertexShader)
        GLES20.glAttachShader(shaderProgram, fragmentShader)
        GLES20.glLinkProgram(shaderProgram)
        
        // 检查着色器程序链接是否成功
        val linkStatus = IntArray(1)
        GLES20.glGetProgramiv(shaderProgram, GLES20.GL_LINK_STATUS, linkStatus, 0)
        if (linkStatus[0] == 0) {
            val log = GLES20.glGetProgramInfoLog(shaderProgram)
            GLES20.glDeleteProgram(shaderProgram)
            throw RuntimeException("着色器程序链接失败: $log")
        }
    }
    
    /**
     * 加载着色器
     */
    private fun loadShader(type: Int, shaderCode: String): Int {
        val shader = GLES20.glCreateShader(type)
        GLES20.glShaderSource(shader, shaderCode)
        GLES20.glCompileShader(shader)
        
        // 检查着色器编译是否成功
        val compileStatus = IntArray(1)
        GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compileStatus, 0)
        if (compileStatus[0] == 0) {
            val log = GLES20.glGetShaderInfoLog(shader)
            GLES20.glDeleteShader(shader)
            throw RuntimeException("着色器编译失败: $log")
        }
        
        return shader
    }
    
    /**
     * 处理触摸事件
     */
    fun handleTouchEvent(event: MotionEvent, width: Int, height: Int): Boolean {
        // 更新视图尺寸
        viewWidth = width
        viewHeight = height
        
        // 使用动作预测器预测触摸事件
        motionEventPredictor?.record(event)
        val predictedEvent = motionEventPredictor?.predict()
        
        // 获取压感值（0.0f到1.0f之间）
        val pressure = event.pressure.coerceIn(0.0f, 1.0f)
        // 根据压感调整线宽（2.0f到8.0f之间）
        currentLineWidth = 2.0f + pressure * 6.0f
        
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                // 开始书写新笔画
                isWriting = true
                currentPath = Path()
                currentPath.moveTo(event.x, event.y)
                
                // 清空当前笔画数据
                synchronized(this) {
                    currentStrokeVertices.clear()
                    currentStrokeWidths.clear()
                    currentStrokePoints.clear()
                    addVertexToCurrentStroke(event.x, event.y, currentLineWidth)
                    
                    // 添加笔画点（用于MiniCPM识别）
                    currentStrokePoints.add(StrokePoint(event.x / viewWidth, event.y / viewHeight))
                }
                
                // 请求渲染
                glView.requestRender()
            }
            MotionEvent.ACTION_MOVE -> {
                if (isWriting) {
                    // 添加路径点
                    currentPath.lineTo(event.x, event.y)
                    
                    synchronized(this) {
                        addVertexToCurrentStroke(event.x, event.y, currentLineWidth)
                        
                        // 添加笔画点（用于MiniCPM识别）
                        currentStrokePoints.add(StrokePoint(event.x / viewWidth, event.y / viewHeight))
                    }
                    
                    // 使用预测点进行预渲染
                    predictedEvent?.let { predicted ->
                        if (predicted.action == MotionEvent.ACTION_MOVE) {
                            val predictedPressure = predicted.pressure.coerceIn(0.0f, 1.0f)
                            val predictedLineWidth = 2.0f + predictedPressure * 6.0f
                            synchronized(this) {
                                addVertexToCurrentStroke(predicted.x, predicted.y, predictedLineWidth)
                            }
                        }
                    }
                    
                    // 请求渲染
                    glView.requestRender()
                }
            }
            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                if (isWriting) {
                    // 结束书写
                    isWriting = false
                    
                    // 将当前笔画保存到已完成笔画列表
                    synchronized(this) {
                        if (currentStrokeVertices.isNotEmpty()) {
                            completedStrokes.add(
                                StrokeData(
                                    vertices = currentStrokeVertices.toList(),
                                    widths = currentStrokeWidths.toList()
                                )
                            )
                        }
                        
                        // 将当前笔画点添加到总笔画点列表
                        if (currentStrokePoints.isNotEmpty()) {
                            allStrokePoints.addAll(currentStrokePoints)
                        }
                        
                        // 清空当前笔画数据
                        currentStrokeVertices.clear()
                        currentStrokeWidths.clear()
                        currentStrokePoints.clear()
                    }
                    
                    // 创建当前路径的副本
                    val pathCopy = Path(currentPath)
                    allPaths.add(pathCopy)
                    strokeCount++
                    
                    // 检查是否完成所有笔画
                    if (strokeCount == requiredStrokeCount) {
                        hasCompletedStrokes = true
                        
                        // 调用MiniCPM进行评分
                        evaluateWithMiniCPM()
                    }
                    
                    // 重置当前路径
                    currentPath = Path()
                    
                    // 请求渲染
                    glView.requestRender()
                }
            }
        }
        
        return true
    }
    
    /**
     * 添加顶点到当前笔画
     */
    private fun addVertexToCurrentStroke(x: Float, y: Float, lineWidth: Float) {
        // 将屏幕坐标转换为OpenGL坐标
        // 修复左右镜像问题：反转X轴
        val glX = 1 - (x / viewWidth) * 2
        val glY = 1 - (y / viewHeight) * 2
        
        currentStrokeVertices.add(glX)
        currentStrokeVertices.add(glY)
        currentStrokeVertices.add(0.0f) // Z坐标
        
        // 添加线宽
        currentStrokeWidths.add(lineWidth)
    }
    
    /**
     * 添加顶点到缓冲区（保留用于田字格等）
     */
    private fun addVertex(x: Float, y: Float, lineWidth: Float) {
        // 将屏幕坐标转换为OpenGL坐标
        // 修复左右镜像问题：反转X轴
        val glX = 1 - (x / viewWidth) * 2
        val glY = 1 - (y / viewHeight) * 2
        
        // 使用同步块确保线程安全
        synchronized(this) {
            lineVertices.add(glX)
            lineVertices.add(glY)
            lineVertices.add(0.0f) // Z坐标
            
            // 添加线宽
            lineWidths.add(lineWidth)
            
            // 更新顶点缓冲区
            updateVertexBufferInternal()
        }
    }
    
    /**
     * 更新顶点缓冲区（线程安全版本）
     */
    private fun updateVertexBuffer() {
        synchronized(this) {
            updateVertexBufferInternal()
        }
    }
    
    /**
     * 更新顶点缓冲区（内部实现）
     */
    private fun updateVertexBufferInternal() {
        if (lineVertices.isEmpty()) {
            vertexBuffer = null
            return
        }
        
        // 创建副本以避免并发修改异常
        val verticesCopy = lineVertices.toFloatArray()
        
        val bb = ByteBuffer.allocateDirect(verticesCopy.size * 4)
        bb.order(ByteOrder.nativeOrder())
        vertexBuffer = bb.asFloatBuffer()
        vertexBuffer?.put(verticesCopy)
        vertexBuffer?.position(0)
    }
    
    /**
     * 绘制田字格（蓝绿色虚线）
     */
    private fun drawGrid() {
        // 临时保存当前顶点数据
        val tempVertices: List<Float>
        val tempBuffer: FloatBuffer?
        val tempLineWidths: List<Float>
        
        synchronized(this) {
            tempVertices = lineVertices.toList()
            tempBuffer = vertexBuffer
            tempLineWidths = lineWidths.toList()
            
            // 清空当前顶点数据
            lineVertices.clear()
            lineWidths.clear()
        }
        
        try {
            // 绘制田字格的四条线（虚线效果）
            drawDashedLine(0.1f, 0.5f, 0.9f, 0.5f) // 中间横线
            drawDashedLine(0.5f, 0.1f, 0.5f, 0.9f) // 中间竖线
            
            // 更新顶点缓冲区
            updateVertexBuffer()
            
            // 绘制田字格
            if (lineVertices.size >= 6 && vertexBuffer != null) {
                // 设置视图矩阵
                Matrix.setLookAtM(viewMatrix, 0, 0f, 0f, -3f, 0f, 0f, 0f, 0f, 1f, 0f)
                
                // 计算投影矩阵
                val ratio = viewWidth.toFloat() / viewHeight.toFloat()
                Matrix.frustumM(projectionMatrix, 0, -ratio, ratio, -1f, 1f, 3f, 7f)
                
                // 计算最终的MVP矩阵
                Matrix.multiplyMM(mvpMatrix, 0, projectionMatrix, 0, viewMatrix, 0)
                
                // 添加着色器程序到OpenGL ES环境
                GLES20.glUseProgram(shaderProgram)
                
                // 获取着色器中的变量位置
                positionHandle = GLES20.glGetAttribLocation(shaderProgram, "vPosition")
                colorHandle = GLES20.glGetUniformLocation(shaderProgram, "vColor")
                mvpMatrixHandle = GLES20.glGetUniformLocation(shaderProgram, "uMVPMatrix")
                
                // 启用顶点数组
                GLES20.glEnableVertexAttribArray(positionHandle)
                
                // 准备顶点坐标数据
                vertexBuffer?.position(0)
                GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer)
                
                // 设置绘制颜色（蓝绿色）
                val gridColor = floatArrayOf(0.0f, 0.7f, 0.7f, 0.6f) // 蓝绿色，半透明
                GLES20.glUniform4fv(colorHandle, 1, gridColor, 0)
                
                // 应用投影和视图变换
                GLES20.glUniformMatrix4fv(mvpMatrixHandle, 1, false, mvpMatrix, 0)
                
                // 绘制田字格线条
                GLES20.glLineWidth(1.5f)
                GLES20.glDrawArrays(GLES20.GL_LINES, 0, lineVertices.size / 3)
                
                // 禁用顶点数组
                GLES20.glDisableVertexAttribArray(positionHandle)
            }
        } finally {
            // 恢复当前顶点数据
            synchronized(this) {
                lineVertices.clear()
                lineVertices.addAll(tempVertices)
                lineWidths.clear()
                lineWidths.addAll(tempLineWidths)
                vertexBuffer = tempBuffer
            }
        }
    }
    
    /**
     * 绘制虚线
     */
    private fun drawDashedLine(x1: Float, y1: Float, x2: Float, y2: Float) {
        val dashLength = 0.03f // 虚线段长度
        val gapLength = 0.02f  // 间隔长度
        val totalLength = sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1))
        
        if (totalLength == 0f) return
        
        val dx = (x2 - x1) / totalLength
        val dy = (y2 - y1) / totalLength
        
        var currentLength = 0f
        var isDash = true
        
        while (currentLength < totalLength) {
            val segmentLength = if (isDash) dashLength else gapLength
            val endLength = minOf(currentLength + segmentLength, totalLength)
            
            if (isDash) {
                val startX = x1 + dx * currentLength
                val startY = y1 + dy * currentLength
                val endX = x1 + dx * endLength
                val endY = y1 + dy * endLength
                
                addVertexForGrid(startX, startY)
                addVertexForGrid(endX, endY)
            }
            
            currentLength = endLength
            isDash = !isDash
        }
    }
    
    /**
     * 为田字格添加顶点
     */
    private fun addVertexForGrid(x: Float, y: Float) {
        // 将归一化坐标转换为OpenGL坐标
        // 修复左右镜像问题：反转X轴
        val glX = 1 - x * 2
        val glY = 1 - y * 2
        
        synchronized(this) {
            lineVertices.add(glX)
            lineVertices.add(glY)
            lineVertices.add(0.0f) // Z坐标
            
            // 添加线宽
            lineWidths.add(1.0f)
        }
    }
    
    /**
     * 绘制具有可变线宽的笔画（真正的压感变化）
     */
    private fun drawStrokeWithVariableWidth(vertices: List<Float>, widths: List<Float>, isCurrentStroke: Boolean) {
        if (vertices.size < 6 || widths.isEmpty()) return
        
        // 设置视图矩阵
        Matrix.setLookAtM(viewMatrix, 0, 0f, 0f, -3f, 0f, 0f, 0f, 0f, 1f, 0f)
        
        // 计算投影矩阵
        val ratio = viewWidth.toFloat() / viewHeight.toFloat()
        Matrix.frustumM(projectionMatrix, 0, -ratio, ratio, -1f, 1f, 3f, 7f)
        
        // 计算最终的MVP矩阵
        Matrix.multiplyMM(mvpMatrix, 0, projectionMatrix, 0, viewMatrix, 0)
        
        // 添加着色器程序到OpenGL ES环境
        GLES20.glUseProgram(shaderProgram)
        
        // 获取着色器中的变量位置
        positionHandle = GLES20.glGetAttribLocation(shaderProgram, "vPosition")
        colorHandle = GLES20.glGetUniformLocation(shaderProgram, "vColor")
        mvpMatrixHandle = GLES20.glGetUniformLocation(shaderProgram, "uMVPMatrix")
        
        // 设置绘制颜色
        val color = if (isCurrentStroke) {
            floatArrayOf(0.0f, 0.47f, 0.95f, 0.9f) // PrimaryBlue，稍微透明
        } else {
            floatArrayOf(0.0f, 0.0f, 0.0f, 0.9f) // Black，稍微透明
        }
        GLES20.glUniform4fv(colorHandle, 1, color, 0)
        
        // 应用投影和视图变换
        GLES20.glUniformMatrix4fv(mvpMatrixHandle, 1, false, mvpMatrix, 0)
        
        // 启用顶点数组
        GLES20.glEnableVertexAttribArray(positionHandle)
        
        // 绘制每个线段，使用对应的线宽
        val pointCount = vertices.size / 3
        val widthCount = widths.size
        
        for (i in 0 until pointCount - 1) {
            // 创建两个点的线段
            val segmentVertices = floatArrayOf(
                vertices[i * 3], vertices[i * 3 + 1], vertices[i * 3 + 2],
                vertices[(i + 1) * 3], vertices[(i + 1) * 3 + 1], vertices[(i + 1) * 3 + 2]
            )
            
            // 创建顶点缓冲区
            val bb = ByteBuffer.allocateDirect(segmentVertices.size * 4)
            bb.order(ByteOrder.nativeOrder())
            val segmentBuffer = bb.asFloatBuffer()
            segmentBuffer.put(segmentVertices)
            segmentBuffer.position(0)
            
            // 准备顶点坐标数据
            GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 0, segmentBuffer)
            
            // 使用当前点的线宽，如果没有对应的线宽则使用默认值
            val currentWidth = if (i < widthCount) {
                widths[i].coerceIn(1.0f, 10.0f)
            } else {
                4.0f
            }
            
            GLES20.glLineWidth(currentWidth)
            GLES20.glDrawArrays(GLES20.GL_LINES, 0, 2)
        }
        
        // 禁用顶点数组
        GLES20.glDisableVertexAttribArray(positionHandle)
    }
    
    /**
     * 使用MiniCPM进行评分
     */
    private fun evaluateWithMiniCPM() {
        // 将笔画数据转换为Stroke对象列表
        val strokes = convertToStrokes()
        
        // 在协程中调用MiniCPM进行评分
        coroutineScope.launch {
            val result = recognitionService.recognizeAndScore(character, strokes)
            onWritingComplete(result)
        }
    }
    
    /**
     * 将笔画点数据转换为Stroke对象列表
     */
    private fun convertToStrokes(): List<Stroke> {
        val strokes = mutableListOf<Stroke>()
        
        // 根据完成的笔画数创建Stroke对象
        // 这里简化处理，假设每个笔画是连续的
        // 在实际应用中，可能需要根据ACTION_UP事件来分割笔画
        val pointsPerStroke = allStrokePoints.size / requiredStrokeCount
        
        for (i in 0 until requiredStrokeCount) {
            val startIndex = i * pointsPerStroke
            val endIndex = if (i == requiredStrokeCount - 1) {
                allStrokePoints.size
            } else {
                (i + 1) * pointsPerStroke
            }
            
            if (startIndex < allStrokePoints.size) {
                val strokePoints = allStrokePoints.subList(startIndex, endIndex)
                strokes.add(Stroke(strokePoints))
            }
        }
        
        return strokes
    }
    
    /**
     * 清除所有路径
     */
    fun clear() {
        synchronized(this) {
            allPaths.clear()
            currentPath = Path()
            lineVertices.clear()
            lineWidths.clear()
            currentStrokeVertices.clear()
            currentStrokeWidths.clear()
            completedStrokes.clear()
            allStrokePoints.clear()
            currentStrokePoints.clear()
            strokeCount = 0
            hasCompletedStrokes = false
            updateVertexBufferInternal()
        }
        requestRender()
    }
    
    /**
     * 请求渲染
     */
    private fun requestRender() {
        // 直接请求GLSurfaceView重新渲染
        // 这将触发onDrawFrame方法的调用
        glView.requestRender()
    }
}